<?php

class App_Service_PayPal {
	
	const SANDBOX_PAYPAL_URL = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
	const SANDBOX_IPN_URL = 'ssl://www.sandbox.paypal.com';
	
	const PAYPAL_URL = 'https://www.paypal.com/cgi-bin/webscr';
	const IPN_URL = 'ssl://www.paypal.com';
	
	private $_lastError; // holds the last error encountered

	private $_testEnv; // bool: testing enviroment?
	private $_ipnLog; // bool: log IPN results to text file?
	private $_ipnLogFile; // filename of the IPN log
	private $_ipnResponse; // holds the IPN response from paypal   
	private $_ipnData = array (); // array contains the POST values for IPN
	
	private $_submitFields = array (); // array holds the _submitFields to submit to paypal
	

	public function __construct( $logFilePath, $env = true ) {
		
		$this->_lastError = '';
		
		$this->_testEnv = $env;
		$this->_ipnLogFile = $logFilePath;
		$this->_ipnLog = true;
		$this->_ipnResponse = '';
		
		// populate $_submitFields array with a few default values.  See the paypal
		// documentation for a list of _submitFields and their data types. These defaul
		// values can be overwritten by the calling script.

		$this->addSubmitField ( 'rm', '2' ); // Return method = POST
		$this->addSubmitField ( 'cmd', '_xclick' );
		$this->addSubmitField ( 'no_shipping', '0' );
		$this->addSubmitField ( 'no_note', '1' );
		$this->addSubmitField ( 'currency_code', 'USD' );
		$this->addSubmitField ( 'lc', 'US' );
		$this->addSubmitField ( 'bn', 'PP-BuyNowBF' );
	}
	
	public function addSubmitField($field, $value) {
		
		// adds a key=>value pair to the _submitFields array, which is what will be 
		// sent to paypal as POST variables.  If the value is already in the 
		// array, it will be overwritten.
		

		$this->_submitFields ["$field"] = $value;
	}
	
	public function validateIPN() {
		
		// read the post from PayPal system and add 'cmd'
		$req = 'cmd=_notify-validate';
		foreach ($_POST as $key => $value) {
			$this->_ipnData ["$key"] = $value;
			$value = urlencode(stripslashes($value));
			$req .= "&$key=$value";
		}

		// post back to PayPal system to validate
		$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
		
		// open the connection to paypal
		$fp = fsockopen ( $this->getURL_IPN() , 443, $errno, $errstr, 30);
		
		if (! $fp) {
			
			// could not open the connection.  If loggin is on, the error message
			// will be in the log.
			$this->_lastError = "fsockopen error no. $errno: $errstr";
			$this->logIPNResults ( false );
			return false;
		
		} else {
			
			// post the data back to paypal
			fputs ($fp, $header . $req);
			
			// loop through the response from the server and append to variable
			while ( ! feof ( $fp ) ) {
				$this->_ipnResponse .= fgets ( $fp, 1024 );
			}
			
			fclose ( $fp ); // close connection
		}
		
		if (eregi ( "VERIFIED", $this->_ipnResponse )) {
			
			// Valid IPN transaction.
			$this->logIPNResults ( true );
			return true;
		
		} else {
			
			// Invalid IPN transaction.  Check the log for details.
			$this->_lastError = 'IPN Validation Failed.';
			$this->logIPNResults ( false );
			return false;
		
		}
	
	}
	
	public function logIPNResults($success) {
		
		$text = "";
		if (! $this->_ipnLog)
			return; // is logging turned off?
		
		// Success or failure being logged?
		if ($success)
			$text .= "SUCCESS! ";
		else
			$text .= "FAIL: " . $this->_lastError;
			
		// Log the POST variables
		$text .= "IPN POST Vars from Paypal: ";
		foreach ( $this->_ipnData as $key => $value ) {
			$text .= "$key=$value, ";
		}
		
		// Log the response from the paypal server
		// $text .= "\nIPN Response from Paypal Server:\n " . $this->_ipnResponse;
		
		// Write to log
		$writer = new Zend_Log_Writer_Stream ( $this->_ipnLogFile );
		$logger = new Zend_Log ( $writer );
		$logger->info ( $text );

	}

	public function getIPNData() {
		return $this->_ipnData;
	}	
	
	public function getIPNResponse() {
		return $this->_ipnResponse;
	}	
	
	public function getSubmitFields() {
		return $this->_submitFields;
	}	

	public function getURL_PayPal() {
		return ($this->_testEnv) ? self::SANDBOX_PAYPAL_URL : self::PAYPAL_URL;
	}	
	
	public function getURL_IPN() {
		return ($this->_testEnv) ? self::SANDBOX_IPN_URL : self::IPN_URL;
	}	
	
	public function getURL($value) {
		switch ($value) {
			case 'SANDBOX_PAYPAL_URL':
				return self::SANDBOX_PAYPAL_URL;
				break;
			case 'SANDBOX_IPN_URL':
				return self::SANDBOX_IPN_URL;
				break;
			case 'PAYPAL_URL':
				return self::PAYPAL_URL;
				break;
			case 'IPN_URL':
				return self::IPN_URL;
				break;
			default:
				return self::PAYPAL_URL;
				break;
		}
	}	
	
}